/*
 * CC3MeshNode.h
 *
 * $Version: cocos3d 0.5.2 (f3df37821a3f) on 2011-03-13 $
 * Author: Bill Hollings
 * Copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
 * http://www.brenwill.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * http://en.wikipedia.org/wiki/MIT_License
 */

/** @file */	// Doxygen marker

#import "CC3Node.h"
#import "CC3MeshModel.h"
#import "CC3Material.h"


#pragma mark -
#pragma mark CC3MeshNode

/**
 * A CC3Node that draws a 3D mesh model.
 * This class forms the base of all visible 3D mesh models in the 3D world.
 *
 * CC3MeshNode is a type of CC3Node, and will often participate in a structural
 * node assembly. An instance can be the child of another node, and the mesh node
 * itself can have child nodes.
 *
 * CC3MeshNodes encapsulate a CC3MeshModel instance, and can also encapsulate either
 * a CC3Material instance, or a pure color. The CC3MeshModel instance contains the
 * mesh vertex data. The CC3Material instance describes the material and texture
 * properties covering the mesh, which are affected by lighting conditions.
 * Alternately, instead of a material, the mesh may be colored by a single pure color
 * via the pureColor property.
 *
 * When this node is drawn, it delegates to the mesh model instance to render the mesh
 * vertices. If a material is defined, before drawing the mesh, it delegates to the
 * material to configure the covering of the mesh. If no material is defined, the node
 * establishes its pure color before rendering the mesh. The pure color is only used
 * if the node has no material attached. And the pure color may in turn be overridden
 * by the mesh data if vertex coloring is in use.
 *
 * Each CC3MeshNode can have only one material or pure color. For large, complicated
 * meshes that are covered by more than one material, or colored with more than one
 * color, the mesh must be broken into smaller meshes, each of which are covered by
 * a single material or color. These smaller sub-meshes are sometimes referred to as
 * "vertex groups". Each such sub-mesh is then wrapped in its own CC3MeshNode instance,
 * along with the material that covers that sub-mesh.
 *
 * These CC3MeshNode instances can then be added as child nodes to a single parent
 * CC3Node instance. This parent CC3Node can then be moved, rotated and scaled,
 * and all of its child nodes will transform in sync. The assembly will behave and
 * be seen as a single object.
 *
 * When the mesh model is set in the meshModel property, the CC3MeshNode instance
 * creates and builds a CC3NodeBoundingVolume instance from the mesh data, and
 * sets it into its boundingVolume property. 
 *
 * When a copy is made of a CC3MeshNode instance using the copy method, a copy is
 * made of the material, but the mesh model is simply assigned by reference, and
 * is not copied. The result is that the the new and original nodes will have
 * different materials, but will share the same mesh model. This design avoids
 * creating multiple copies of volumnious and static mesh data when creating
 * copies of nodes.
 */
@interface CC3MeshNode : CC3LocalContentNode {
	CC3MeshModel* meshModel;
	CC3Material* material;
	ccColor4F pureColor;
}

/**
 * The mesh model that holds the vertex data for this mesh node.
 *
 * When this property is set, if this node has a boundingVolume, it is forced
 * to rebuild itself, otherwise, if this node does not have a boundingVolume,
 * a default bounding volume is created from the mesh model.
 */
@property(nonatomic, retain) CC3MeshModel* meshModel;

/** The material covering this mesh node. */
@property(nonatomic, retain) CC3Material* material;

/**
 * The pure, solid color used to paint the mesh if no material is established for this node.
 * This color is not not be affected by the lighting conditions. The mesh will always appear
 * in the same pure, solid color, regardless of the lighting sources.
 */
@property(nonatomic, assign) ccColor4F pureColor;


#pragma mark Material coloring

/**
 * The ambient color of the material of this mesh node.
 *
 * Material color is initially set to kCC3DefaultMaterialColorAmbient.
 * If this instance has no material, this property will return kCCC4FBlackTransparent.
 *
 * The value of this property is also affected by changes to the color and opacity
 * properties. See the notes for those properties for more information.
 */
@property(nonatomic, assign) ccColor4F ambientColor;

/**
 * The diffuse color of the material of this mesh node.
 *
 * Material color is initially set to kCC3DefaultMaterialColorDiffuse.
 * If this instance has no material, this property will return kCCC4FBlackTransparent.
 *
 * The value of this property is also affected by changes to the color and opacity
 * properties. See the notes for those properties for more information.
 */
@property(nonatomic, assign) ccColor4F diffuseColor;

/**
 * The specular color of the material of this mesh node.
 *
 * Material color is initially set to kCC3DefaultMaterialColorSpecular.
 * If this instance has no material, this property will return kCCC4FBlackTransparent.
 *
 * The value of this property is also affected by changes to the opacity property.
 * See the notes for the opacity property for more information.
 */
@property(nonatomic, assign) ccColor4F specularColor;

/**
 * The emission color of the material of this mesh node.
 *
 * Material color is initially set to kCC3DefaultMaterialColorEmission.
 * If this instance has no material, this property will return kCCC4FBlackTransparent.
 *
 * The value of this property is also affected by changes to the opacity property.
 * See the notes for the opacity property for more information.
 */
@property(nonatomic, assign) ccColor4F emissionColor;


#pragma mark CCRGBAProtocol support

/**
 * Implementation of the CCRGBAProtocol color property.
 *
 * Querying this property returns the RGB components of the material's diffuseColor
 * property, or of this node's pureColor property if this node has no material.
 * In either case, the RGB values are converted from the floating point range (0 to 1),
 * to the byte range (0 to 255).
 *
 * When setting this property, the RGB values are each converted to a floating point
 * number between 0 and 1, and are set into both the ambientColor and diffuseColor
 * properties of this node's material, and the pureColor property of this node.
 * The alpha of each of those properties remains unchanged.
 *
 * Setting this property also sets the same property on all descendant nodes.
 */
@property(nonatomic, assign) ccColor3B color;

/**
 * Implementation of the CCRGBAProtocol opacity property.
 *
 * Querying this property returns the alpha component of the material's diffuseColor
 * property, or of this node's pureColor property if this node has no material.
 * In either case, the RGB values are converted from the floating point range (0 to 1),
 * to the byte range (0 to 255).
 *
 * When setting this property, the value is converted to a floating point number
 * between 0 and 1, and is set into all of the ambientColor, diffuseColor,
 * specularColor, and emissionColor properties of this node's material, and the
 * pureColor property of this node 
 * The RGB components of each of those properties remains unchanged.
 *
 * Setting this property also sets the same property on all descendant nodes.
 *
 * See the notes for this property on CC3Material for more information on how this
 * property interacts with the other material properties.
 *
 * Setting this property should be thought of as a convenient way to switch between the
 * two most common types of blending combinations. For finer control of blending, set
 * specific blending properties on the CC3Material instance directly, and avoid making
 * changes to this property.
 */
@property(nonatomic, assign) GLubyte opacity;

/**
 * Indicates whether the material of this mesh node is opaque.
 *
 * If this node has a material, returns the value of the same property on the material.
 * If this node has no material, return YES if the alpha component of the pureColor
 * property is 1.0, otherwise returns NO.
 *
 * Setting this property sets the same property in the material and in all descendants,
 * and sets the alpha component of the pureColor property to 1.0.
 *
 * See the notes for this property on CC3Material for more information on how this
 * property interacts with the other material properties.
 *
 * Setting this property should be thought of as a convenient way to switch between the
 * two most common types of blending combinations. For finer control of blending, set
 * specific blending properties on the CC3Material instance directly, and avoid making
 * changes to this property.
 */
@property(nonatomic, assign) BOOL isOpaque;


#pragma mark Drawing

/**
 * Draws the local content of this mesh node by following these steps:
 *   -# If the shouldDecorateNode property of the visitor is YES, and this node has a
 *      material, invokes the draw method of the material. Otherwise, invokes the
 *      CC3Material class-side unbind method.
 *   -# Invokes the drawWithVisitor: method of the encapsulated mesh model.
 *
 * This method is called automatically from the transformAndDrawWithVisitor: method
 * of this node. Usually, the application never needs to invoke this method directly.
 */
-(void) drawLocalContentWithVisitor: (CC3NodeDrawingVisitor*) visitor;


#pragma mark Allocation and initialization

/**
 * Populates this instance as a simple single-color rectangular mesh of the specified size,
 * centered at the origin, and laid out on the X-Y plane.
 *
 * The specified color will not be affected by the lighting conditions. The rectangle
 * will always appear in the same pure, solid color, regardless of the lighting sources.
 *
 * As this node is translated, rotate and scaled, the rectangle will be re-oriented in 3D space.
 *
 * This is a convenience method for creating a simple, but useful shape, which can be
 * used to create walls, floors, signs, etc.
 */
-(void) populateAsCenteredRectangleWithSize: (CGSize) rectSize
							   andPureColor: (ccColor4F) aColor;

/**
 * Populates this instance as a simple single-color rectangular mesh of the specified size,
 * with the specified pivot point at the origin, and laid out on the X-Y plane.
 *
 * The specified color will not be affected by the lighting conditions. The rectangle
 * will always appear in the same pure, solid color, regardless of the lighting sources.
 *
 * The pivot point can be any point within the rectangle's size. For example, if the
 * pivot point is {0, 0}, the rectangle will be laid out so that the bottom-left corner
 * is at the origin. Or, if the pivot point is in the center of the rectangle's size,
 * the rectangle will be laid out centered on the origin, as in the
 * populateAsCenteredRectangleWithSize:withTexture: method.
 *
 * As this node is translated, rotate and scaled, the rectangle will be re-oriented in 3D space.
 *
 * This is a convenience method for creating a simple, but useful shape, which can be
 * used to create walls, floors, signs, etc.
 */
-(void) populateAsRectangleWithSize: (CGSize) rectSize
						   andPivot: (CGPoint) pivot
					   andPureColor: (ccColor4F) aColor;
	
/**
 * Populates this instance as a simple textured rectangular mesh of the specified size,
 * centered at the origin, and laid out on the X-Y plane.
 *
 * The shouldInvert flag indicates whether the texture should be inverted when laid out
 * on the mesh. Some textures appear inverted after loading under iOS. This flag can be
 * used to compensate for that by reinverting the texture to the correct orientation.
 *
 * As this node is translated, rotate and scaled, the textured rectangle will be
 * re-oriented in 3D space.
 *
 * This is a convenience method for creating a simple, but useful shape, which can be
 * used to create walls, floors, etc.
 */
-(void) populateAsCenteredRectangleWithSize: (CGSize) rectSize
								withTexture: (CC3Texture*) texture
							  invertTexture: (BOOL) shouldInvert;

/**
 * Populates this instance as a simple textured rectangular mesh of the specified size,
 * with the specified pivot point at the origin, and laid out on the X-Y plane.
 *
 * The pivot point can be any point within the rectangle's size. For example, if the
 * pivot point is {0, 0}, the rectangle will be laid out so that the bottom-left corner
 * is at the origin. Or, if the pivot point is in the center of the rectangle's size,
 * the rectangle will be laid out centered on the origin, as in the
 * populateAsCenteredRectangleWithSize:withTexture: method.
 *
 * The shouldInvert flag indicates whether the texture should be inverted when laid out
 * on the mesh. Some textures appear inverted after loading under iOS. This flag can be
 * used to compensate for that by reinverting the texture to the correct orientation.
 *
 * As this node is translated, rotate and scaled, the textured rectangle will be
 * re-oriented in 3D space.
 *
 * This is a convenience method for creating a simple, but useful shape, which can be
 * used to create walls, floors, etc.
 */
-(void) populateAsRectangleWithSize: (CGSize) rectSize
						   andPivot: (CGPoint) pivot
						withTexture: (CC3Texture*) texture
					  invertTexture: (BOOL) shouldInvert;

/**
 * Populates this instance as a wire-frame box with the specified dimensions.
 *
 * The lines of the wire-frame will be drawn in the specified color, which will not be
 * affected by the lighting conditions. The wire-frame box will always appear in the same
 * pure, solid color, regardless of the lighting sources.
 *
 * As this node is translated, rotate and scaled, the rectangle will be re-oriented in 3D space.
 *
 * This is a convenience method for creating a simple, but useful shape, which can be
 * used to create walls, floors, signs, etc.
 */
-(void) populateAsWireBox: (CC3BoundingBox) box withPureColor: (ccColor4F) aColor;

@end


#pragma mark -
#pragma mark CC3LineNode

/**
 * CC3LineNode is a type of CC3MeshNode that is specialized to display lines. It includes
 * properties for setting the line width, and whether or not the lines should be smoothed
 * using automatic anti-aliasing.
 *
 * To draw lines, you must make sure that the drawingMode property of the vertex array that
 * performs the drawing within the meshModel (either the vertexIndices or vertexLocations
 * instance) is set to one of GL_LINES, GL_LINE_STRIP or GL_LINE_LOOP. Other than that,
 * you configure the mesh node and its mesh model as you would with any mesh node.
 *
 * For a simple wire box, you can use the populateAsWireBox:withPureColor: convenience
 * method of CC3MeshNode.
 *
 * To color the lines, use the pureColor property to draw the lines in a pure, solid color
 * that is not affected by lighting conditions. You can also add a material to your
 * CC3LineNode instance to get more subtle coloring and blending, but this can sometimes
 * appear strange with lines. You can also use CCActionInterval to change the tinting or
 * opacity of the lines, as you would with any mesh node.
 *
 * You can review the implementation source code of the populateAsWireBox:withPureColor:
 * method of CC3MeshNode for an example of constructing a CC3LineNode instance to draw
 * lines. The method is actually implemented on CC3MeshNode, because any CC3MeshNode can
 * be configured to draw lines, but usually you would invoke that method on an instance
 * of the CC3LineNode subclass.
 */
@interface CC3LineNode : CC3MeshNode {
	GLfloat lineWidth;
	BOOL shouldSmoothLines;
}

/** The width of the lines that will be drawn. The initial value is 1.0. */
@property(nonatomic, assign) GLfloat lineWidth;

/** Indicates whether lines should be smoothed (antialiased). The initial value is NO. */
@property(nonatomic, assign) BOOL shouldSmoothLines;

@end


#pragma mark -
#pragma mark CC3PlaneNode

/**
 * CC3PlaneNode is a type of CC3MeshNode that is specialized to display planes and
 * simple rectanglular meshes.
 *
 * Since a plane is a mesh like any other mesh, the functionality required to create
 * and manipulate plane meshes is present in the CC3MeshNode class, and if you choose,
 * you can create and manage planes meshes using that class alone. CC3PlaneNode exists
 * for the most part simply to identify rectangular meshes as such. However, in future,
 * additional state or behaviour may be added to this class.
 * 
 * Several convenience methods exist in the CC3MeshNode class to aid in constructing a
 * CC3PlaneNode instance:
 *   - populateAsCenteredRectangleWithSize:andPureColor:
 *   - populateAsRectangleWithSize:andPivot:andPureColor:
 *   - populateAsCenteredRectangleWithSize:withTexture:invertTexture:
 *   - populateAsRectangleWithSize:andPivot:withTexture:invertTexture:
 */
@interface CC3PlaneNode : CC3MeshNode
@end



